package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	logger "github.com/sirupsen/logrus"
)

type dingHook struct {
	apiUrl     string //钉钉 群机器人token url
	levels     []logger.Level
	atMobiles  []string    // at谁
	appName    string      // 模块前缀
	jsonBodies chan []byte //异步发送内容队列
	closeChan  chan bool   //主进程关闭消息通道
}

//- Levels 代表在哪几个级别下应用这个hook

func (dh *dingHook) Levels() []logger.Level {
	return dh.levels
}

//- Fire 代表 执行具体什么逻辑
func (dh *dingHook) Fire(e *logger.Entry) error {
	msg, _ := e.String()
	dh.DirectSend(msg)
	return nil
}

// 同步发送钉钉的函数
func (dh *dingHook) DirectSend(msg string) {
	dm := dingMsg{
		MsgType: "text",
	}
	dm.Text.Content = fmt.Sprintf("[日志告警log]\n[app=%s]\n"+
		"[日志详情:%s]", dh.appName, msg)

	dm.At.AtMobiles = dh.atMobiles
	bs, err := json.Marshal(dm)
	if err != nil {
		logger.Errorf("[消息json.marshal失败][error:%v][msg:%v]", err, msg)
		return
	}
	// dh.jsonBodies <- bs

	go func() {
		dh.jsonBodies <- bs
	}()
}

// 定义发钉钉信息的字段
/*
{
    "at": {
        "atMobiles":[
            "180xxxxxx"
        ],
        "atUserIds":[
            "user123"
        ],
        "isAtAll": false
    },
    "text": {
        "content":"我就是我, @XXX 是不一样的烟火"
    },
    "msgtype":"text"
}
*/
type dingMsg struct {
	MsgType string `json:"msgtype"`
	Text    struct {
		Content string `json:"content"`
	} `json:"text"`
	At struct {
		AtMobiles []string `json:"atMobiles"`
	} `json:"at"`
}

func main() {
	dh := &dingHook{
		apiUrl:     "https://oapi.dingtalk.com/robot/send?access_token=1b08230772e74caed97e72c5d3892e0cb8d432f8eeba05f777eew6a5c58cc6",
		levels:     []logger.Level{logger.WarnLevel, logger.InfoLevel},
		atMobiles:  []string{"172332240"},
		appName:    "TEST",
		jsonBodies: make(chan []byte),
		closeChan:  make(chan bool),
	}

	level := logger.InfoLevel
	logger.SetLevel(level)
	// 设置filename
	logger.SetReportCaller(true)

	logger.SetFormatter(&logger.JSONFormatter{

		TimestampFormat: "2006-01-02 15:04:05",
	})
	// 添加hook
	logger.AddHook(dh)
	go dh.postMsg()
	for i := 0; i < 10; i++ {
		logger.Info(fmt.Sprintf("这是我自己hook的logrus %d", i))
		time.Sleep(5 * time.Second)
	}

}

func (dh *dingHook) postMsg() {
	for {
		select {
		case bs := <-dh.jsonBodies:
			dmsg := dingMsg{}
			err := json.Unmarshal(bs, &dmsg)
			if err != nil {
				fmt.Printf("[反解析失败][error:%v][msg:%v]", err, dmsg.Text)
				return
			}
			res, err := http.Post(dh.apiUrl, "application/json", bytes.NewBuffer(bs))
			if err != nil {
				logger.Errorf("[消息发送失败][error:%v][msg:%v]", err, dmsg.Text)
				return
			}
			if res != nil && res.StatusCode != 200 {
				logger.Errorf("[钉钉返回错误][StatusCode:%v][msg:%v]", res.StatusCode, dmsg.Text)
				return
			}
		}
	}


}
